package com.demon.activitychange.xposed;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.widget.Checkable;
import android.widget.EditText;

import com.alibaba.fastjson.JSON;
import com.demon.activitychange.net.Callback;
import com.demon.activitychange.net.impl.MD5Util;
import com.demon.activitychange.persist.impl.FilePersist;
import com.demon.activitychange.util.FileUtil;
import com.demon.activitychange.util.JSONObjectPack;
import com.demon.activitychange.util.TraceUtil;
import com.demon.activitychange.xposed.HookMain.DyOperEnum;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

public class HookNormHandler {
    private Handler mainHandler = new Handler(Looper.getMainLooper());
    private Activity mainActivityObj, dYLoginActivityObj, updatePasswordActivityObj;
    private Object mainPageFragmentObj;
    private Bundle dyLoginBundle;
    private Class DYLoginActivityCls, UpdatePasswordActivityCls, PhoneBeanCls;
    private volatile DyOperEnum mOperEnum = DyOperEnum.unknown;
    private String mPhone, mPrefix, mPass, mCode, mMessageList, mUserId;
    private JSONObject mLoginInfo = new JSONObject();
    private volatile boolean isPassLoginSuccess = true;
    private Executor executor = Executors.newSingleThreadExecutor();

    void hook(ClassLoader appClassLoader, Context context) {
        try {
            mPrefix = (String) FilePersist.newInstance(HookMain.PACKAGE_ID_NORM).readData("device", "8612");
            mPhone = (String) FilePersist.newInstance(HookMain.PACKAGE_ID_NORM).readData("phone", "18566506650");

            hookDevice(appClassLoader, context);
            hookDeviceId(appClassLoader, context);
            hookDialog(appClassLoader, context);
            hookNet(appClassLoader, context);
            hookLogin(appClassLoader, context);
            hookIM(appClassLoader, context);
        } catch (Exception e) {
            TraceUtil.xe("" + e.getMessage());
        }
    }

    private void hookDevice(final ClassLoader classLoader, final Context context) {
        TraceUtil.e("hookDevice");
        Class TelephonyManagerCls = XposedHelpers.findClass("android.telephony.TelephonyManager", classLoader);
        XposedHelpers.findAndHookMethod(TelephonyManagerCls, "getDeviceId", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                String deviceId = (String) param.getResult();
                String nDeviceId = mPrefix + mPhone;
                // TraceUtil.e("deviceId: prev = " + deviceId + ", nDeviceId = " + nDeviceId);
                param.setResult(nDeviceId);
            }
        });
        XposedHelpers.findAndHookMethod(TelephonyManagerCls, "getDeviceId", int.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                String deviceId = (String) param.getResult();
                String nDeviceId = mPrefix + mPhone;
                param.setResult(nDeviceId);
            }
        });
        Class WifiInfoCls = XposedHelpers.findClass("android.net.wifi.WifiInfo", classLoader);
        XposedHelpers.findAndHookMethod(WifiInfoCls, "getMacAddress", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                String mac = (String) param.getResult();
                String nMac = MD5Util.GetMD5Code(mPrefix + mPhone).substring(20);
                nMac = nMac.replaceAll("(.{2})", "$1:").substring(0, 17);
                // TraceUtil.e("mac: prev = " + mac + ", new = " + nMac);
                param.setResult(nMac);
            }
        });
        Class SettingsCls = XposedHelpers.findClass("android.provider.Settings.Secure", classLoader);
        XposedHelpers.findAndHookMethod(SettingsCls, "getString", ContentResolver.class, String.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                if ("android_id".equals(param.args[1])) {
                    String androidId = (String) param.getResult();
                    String nAndroidId = MD5Util.GetMD5Code(mPrefix + mPhone).substring(0, 16);
                    // TraceUtil.e("androidId: prev = " + androidId + ", new = " + nAndroidId);
                    param.setResult(nAndroidId);
                }
            }
        });
    }

    private void hookDeviceId(final ClassLoader classLoader, final Context context) {
        TraceUtil.e("hookDeviceId");
        // device_register接口，post 数据不加密
        Class AppLogCls = XposedHelpers.findClass("com.ss.android.common.applog.AppLog", classLoader);
        XposedHelpers.findAndHookMethod(AppLogCls, "getLogEncryptSwitch", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                param.setResult(false);
            }
        });

        Class DeviceRegisterThreadCls = XposedHelpers.findClass("com.ss.android.deviceregister.b.b.a", classLoader);
        XposedHelpers.findAndHookMethod(DeviceRegisterThreadCls, "a", String.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                String postParam = (String) param.args[0];
                // TraceUtil.e("post param: " + postParam);
                JSONObject postObj = new JSONObject(postParam);
                JSONObject obj = postObj.getJSONObject("header");
                if (obj != null) {
                    obj.put("apk_first_install_time", 0);
                }

                String nPostParam = postObj.toString();
                // TraceUtil.e("post nParam: " + nPostParam);
                param.args[0] = nPostParam;
            }
        });
    }

    private void hookDialog(final ClassLoader classLoader, final Context context) {
        TraceUtil.e("hookDialog");
        Class RemindCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.main.cz", classLoader);
        XposedHelpers.findAndHookMethod(RemindCls, "onCreate", Bundle.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("remind dialog onCreate");
                final Dialog dialog = (Dialog) param.thisObject;
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        int confirmId = dialog.getContext().getResources().getIdentifier("aji", "id", dialog.getContext().getPackageName());
                        dialog.findViewById(confirmId).performClick();
                    }
                });
            }
        });

        Class UpdateXCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.update.x", classLoader);
        XposedHelpers.findAndHookMethod(UpdateXCls, "onCreate", Bundle.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("update dialog onCreate");
                final Dialog dialog = (Dialog) param.thisObject;
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        int cancelId = dialog.getContext().getResources().getIdentifier("cx4", "id", dialog.getContext().getPackageName());
                        dialog.findViewById(cancelId).performClick();
                    }
                });
            }
        });
    }

    private void hookNet(final ClassLoader classLoader, final Context context) {
        TraceUtil.e("hookNet");

        // 获取网络请求的header、cookie
        Class UrlRequestBuilderImplCls = XposedHelpers.findClass("com.ttnet.org.chromium.net.impl.UrlRequestBuilderImpl", classLoader);
        XposedHelpers.findAndHookMethod(UrlRequestBuilderImplCls, "build", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Object obj = param.thisObject;
                String url = (String) XposedHelpers.getObjectField(obj, "mUrl");
                Object headers = XposedHelpers.getObjectField(obj, "mRequestHeaders");
//                if (!TextUtils.isEmpty(url) &&
//                        (url.contains("?is_after_login") || url.contains("/passport/mobile/send_code") || url.contains("/passport/mobile/login") || url.contains("/passport/mobile/sms_login"))) {
//                    TraceUtil.e("req url = " + url + ", header = " + JSON.toJSONString(headers));
//                    // StackTraceElement[] stacks = Thread.currentThread().getStackTrace();
//                    // TraceUtil.e("req stacks: " + Arrays.toString(stacks));
//                }

                if (!TextUtils.isEmpty(url) && (url.contains("?is_after_login"))) {
                    String headerStr = JSON.toJSONString(headers);
                    TraceUtil.e("req url = " + url + ", header = " + headerStr);
                    url = PayUtils.getMidText(url, "is_after_login=", "");
                    url = url.substring(1);
                    mLoginInfo = new JSONObjectPack()
                            .putValue("phone", mPhone)
                            .putValue("urlParam", url)
                            .putValue("header", headerStr)
                            .getJSONObject();

                    if (mOperEnum == DyOperEnum.login) {
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                TraceUtil.e("****** dy passport login end ******");
                                sendResult(mainActivityObj, DyOperEnum.login.getResult(), 0, mLoginInfo, "");
                                clearExitApp(mainActivityObj);
                            }
                        });

                    } else if (mOperEnum == DyOperEnum.smsLogin) {
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                TraceUtil.e("****** dy passport sms login end ******");
                                sendResult(mainActivityObj, DyOperEnum.smsLogin.getResult(), 0, mLoginInfo, "");
                                clearExitApp(mainActivityObj);
                            }
                        });
                    }
                }

                // 监听device_register接口
                if (!TextUtils.isEmpty(url) && (url.contains("/device_register"))) {
                    TraceUtil.e("req url = " + url);
                    if (mOperEnum == DyOperEnum.login || mOperEnum == DyOperEnum.message) {
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                loginPage();
                            }
                        });
                    } else if (mOperEnum == DyOperEnum.sendCode) {
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                sendCodePage();
                            }
                        });
                    }
                }
            }
        });

        // 获取网络请求的结果
        Class SsHttpCallCls = XposedHelpers.findClass("com.bytedance.retrofit2.SsHttpCall", classLoader);
        XposedBridge.hookAllMethods(SsHttpCallCls, "execute", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                Object ssResponse = param.getResult();
                if (ssResponse == null) {
                    TraceUtil.e("res is null");
                    return;
                }
                Object rawResponse = XposedHelpers.callMethod(ssResponse, "raw");
                String url = (String) XposedHelpers.getObjectField(rawResponse, "url");
                if (!TextUtils.isEmpty(url) && (url.contains("/device_register") || url.contains("?is_after_login") ||
                        url.contains("/passport/mobile/send_code") || url.contains("/passport/mobile/login") || url.contains("/passport/mobile/sms_login") ||
                        url.contains("/passport/password/check") || url.contains("/passport/password/change"))) {
                    int status = XposedHelpers.getIntField(rawResponse, "status");
                    byte[] bodyByte = (byte[]) XposedHelpers.getObjectField(XposedHelpers.getObjectField(rawResponse, "body"), "bytes");
                    String body = new String(bodyByte);
                    TraceUtil.e("res success, status = " + status + ", url = " + url + ", body = " + body);

                    if (url.contains("/passport/mobile/send_code") && mOperEnum == DyOperEnum.sendCode) {
                        JSONObject obj = new JSONObject(body);
                        String message = obj.optString("message");
                        TraceUtil.e("****** dy passport send code end ******");
                        if ("success".equals(message)) {
                            sendResult(mainActivityObj, DyOperEnum.sendCode.getResult(), 0, null, "");
                        } else {
                            JSONObject data = obj.optJSONObject("data");
                            final String msg = "error_code = " + data.optString("error_code") + ", description = " + data.optString("description");
                            mainHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    sendResult(mainActivityObj, DyOperEnum.sendCode.getResult(), 1, null, msg);
                                    clearExitApp(mainActivityObj);
                                }
                            });
                        }
                    }

                    // {"data":{"captcha":"","desc_url":"","description":"为保证帐号安全，请使用手机验证码登录","error_code":1039,"mobile_ticket":"","verify_mobile":""},"message":"error"}
                    else if (url.contains("/passport/mobile/login") && (mOperEnum == DyOperEnum.login || mOperEnum == DyOperEnum.message)) {
                        JSONObject obj = new JSONObject(body);
                        String message = obj.optString("message");
                        if ("error".equals(message)) {
                            JSONObject data = obj.optJSONObject("data");
                            final String msg = "error_code = " + data.optString("error_code") + ", description = " + data.optString("description");
                            mainHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    TraceUtil.e("****** dy passport login failed ******");
                                    if (mOperEnum == DyOperEnum.login) {
                                        isPassLoginSuccess = false;
                                        // sendResult(mainActivityObj, DyOperEnum.login.getResult(), 1, null, msg);
                                        // clearExitApp(mainActivityObj);
                                    } else if (mOperEnum == DyOperEnum.message) {
                                        isPassLoginSuccess = false;
                                        // sendResult(mainActivityObj, DyOperEnum.message.getResult(), 1, null, msg);
                                        // clearExitApp(mainActivityObj);
                                    }
                                }
                            });
                        } else {
                            JSONObject data = obj.optJSONObject("data");
                            if (mOperEnum == DyOperEnum.message) {
                                mUserId = data.optString("user_id");
                                TraceUtil.e("****** dy passport login success，user_id = " + mUserId + " ******");
                            }
                        }
                    }
                }
            }
        });

        // 打印网络请求的日志
//        Class LoggerCls = XposedHelpers.findClass("com.ttnet.org.chromium.base.Logger", classLoader);
//        XposedHelpers.findAndHookMethod(LoggerCls, "debug", new XC_MethodHook() {
//            @Override
//            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//                super.afterHookedMethod(param);
//                param.setResult(true);
//            }
//        });
//        XposedHelpers.findAndHookMethod(LoggerCls, "d", String.class, String.class, new XC_MethodHook() {
//            @Override
//            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//                super.afterHookedMethod(param);
//                if ("CronetHttpURLConnection".equals(param.args[0])) {
//                    String log = (String) param.args[1];
//                    if (!TextUtils.isEmpty(log) &&
//                            (log.contains("?is_after_login") || log.contains("/passport/mobile/send_code") || log.contains("/passport/mobile/login") || log.contains("/passport/mobile/sms_login"))) {
//                        TraceUtil.e("log: " + log);
//                        // StackTraceElement[] stacks = Thread.currentThread().getStackTrace();
//                        // TraceUtil.e("log: " + param.args[1] + "，\r\nstack: " + Arrays.toString(stacks));
//                    }
//                }
//            }
//        });

        // 监听网络请求的res
//        Class CronetUrlRequestCallbackCls = XposedHelpers.findClass("com.ttnet.org.chromium.net.urlconnection.CronetHttpURLConnection.CronetUrlRequestCallback", classLoader);
//        XposedBridge.hookAllMethods(CronetUrlRequestCallbackCls, "onSucceeded", new XC_MethodHook() {
//            @Override
//            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//                super.afterHookedMethod(param);
//                Object urlResponseInfo = param.args[1];
//                String url = (String) XposedHelpers.callMethod(urlResponseInfo, "getUrl");
//                int statusCode = (int) XposedHelpers.callMethod(urlResponseInfo, "getHttpStatusCode");
//                String statusText = (String) XposedHelpers.callMethod(urlResponseInfo, "getHttpStatusText");
//                if (!TextUtils.isEmpty(url) &&
//                        (url.contains("?is_after_login") || url.contains("/passport/mobile/send_code") || url.contains("/passport/mobile/login") || url.contains("/passport/mobile/sms_login"))) {
//                    TraceUtil.e("res success, url = " + url + ", statusCode = " + statusCode + ", statusText = " + statusText);
//                }
//            }
//        });
//        XposedBridge.hookAllMethods(CronetUrlRequestCallbackCls, "onFailed", new XC_MethodHook() {
//            @Override
//            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//                super.afterHookedMethod(param);
//                Object urlResponseInfo = param.args[1];
//                String url = (String) XposedHelpers.callMethod(urlResponseInfo, "getUrl");
//                int statusCode = (int) XposedHelpers.callMethod(urlResponseInfo, "getHttpStatusCode");
//                String statusText = (String) XposedHelpers.callMethod(urlResponseInfo, "getHttpStatusText");
//                TraceUtil.e("res fail, url = " + url + ", statusCode = " + statusCode + ", statusText = " + statusText);
//                if (!TextUtils.isEmpty(url) &&
//                        (url.contains("?is_after_login") || url.contains("/passport/mobile/send_code") || url.contains("/passport/mobile/login") || url.contains("/passport/mobile/sms_login"))) {
//                    TraceUtil.e("res fail, url = " + url + ", statusCode = " + statusCode + ", statusText = " + statusText);
//                }
//            }
//        });
    }

    private void hookLogin(final ClassLoader classLoader, final Context context) {
        TraceUtil.e("hookLogin");
        IntentFilter filter = new IntentFilter();
        filter.addAction(DyOperEnum.smsLogin.getBroadcast());
        filter.addAction(DyOperEnum.smsReg.getBroadcast());
        filter.addAction(DyOperEnum.smsUpdatePassword.getBroadcast());
        filter.addAction(DyOperEnum.exit.getBroadcast());
        context.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(final Context context, final Intent intent) {
                String action = intent.getAction();
                TraceUtil.e("receive broadcast action " + action);
                mainHandler.removeCallbacksAndMessages(null);
                if (DyOperEnum.smsLogin.getBroadcast().equals(action)) {
                    mOperEnum = DyOperEnum.smsLogin;
                    mCode = intent.getStringExtra("code");
                    smsLoginOper(dYLoginActivityObj, mCode, "");
                } else if (DyOperEnum.smsReg.getBroadcast().equals(action)) {
                    mOperEnum = DyOperEnum.smsReg;
                    mCode = intent.getStringExtra("code");
                    mPass = intent.getStringExtra("password");
                    smsLoginOper(dYLoginActivityObj, mCode, mPass);
                } else if (DyOperEnum.smsUpdatePassword.getBroadcast().equals(action)) {
                    mOperEnum = DyOperEnum.smsUpdatePassword;
                    mCode = intent.getStringExtra("code");
                    smsConfirmUpdatePasswordOper(updatePasswordActivityObj, mCode);
                } else if (DyOperEnum.exit.getBroadcast().equals(action)) {
                    mainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            clearExitAppNoRes(context);
                        }
                    });
                }
            }
        }, filter);

        PhoneBeanCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.account.login.c.a.b", classLoader);

        Class MainActivity = XposedHelpers.findClass("com.ss.android.ugc.aweme.main.MainActivity", classLoader);
        XposedHelpers.findAndHookMethod(MainActivity, "onCreate", Bundle.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("MainActivity onCreate");
                mainActivityObj = (Activity) param.thisObject;
                mPhone = (String) FilePersist.newInstance(HookMain.PACKAGE_ID_NORM).readData("phone", "18566506650");
                Intent getIntent = mainActivityObj.getIntent();
                if (getIntent != null) {
                    Bundle bundle = getIntent.getExtras();
                    TraceUtil.e("MainActivity bundle: " + (bundle != null ? bundle.toString() : "null"));
                    if (bundle != null) {
                        String cmd = bundle.getString("cmd");
                        String data = bundle.getString("data");
                        if (data == null) data = "";
                        JSONObject jsObj = new JSONObject();
                        try {
                            jsObj = new JSONObject(data);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }

                        if (!TextUtils.isEmpty(cmd)) {
                            if (DyOperEnum.login.toString().equals(cmd)) {
                                isPassLoginSuccess = true;
                                mOperEnum = DyOperEnum.login;
                                mPhone = jsObj.optString("phone");
                                mPass = jsObj.optString("password");
                            } else if (DyOperEnum.sendCode.toString().equals(cmd)) {
                                mOperEnum = DyOperEnum.sendCode;
                                mPhone = jsObj.optString("phone");
                            } else if (DyOperEnum.message.toString().equals(cmd)) {
                                isPassLoginSuccess = true;
                                mOperEnum = DyOperEnum.message;
                                mPhone = jsObj.optString("phone");
                                mPass = jsObj.optString("password");
                                mMessageList = jsObj.optString("pList");

                                SharedPreferences sp = mainActivityObj.getSharedPreferences("aweme_user", Context.MODE_PRIVATE);
                                mUserId = sp.getString("latest_logged_in_uid_list", "");
                                TraceUtil.e("****** dy logined，user_id = " + mUserId + " ******");
                                if (!TextUtils.isEmpty(mUserId)) {
                                    mainHandler.postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                            if (isPassLoginSuccess) {
                                                TraceUtil.e("dy send msg 超时");
                                                sendResult(mainActivityObj, DyOperEnum.message.getResult(), 1, null, "发送超时");
                                                clearExitApp(mainActivityObj);
                                            }
                                        }
                                    }, 30000);
                                } else {
                                    sp = mainActivityObj.getSharedPreferences("applog_stats", Context.MODE_PRIVATE);
                                    String deviceId = sp.getString("device_id", "");
                                    TraceUtil.e("****** dy logined，deviceId = " + deviceId + " ******");
                                    if (!TextUtils.isEmpty(deviceId)) {
                                        mainHandler.postDelayed(new Runnable() {
                                            @Override
                                            public void run() {
                                                loginPage();
                                            }
                                        }, 3000);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
        XposedHelpers.findAndHookMethod(MainActivity, "onResume", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("MainActivity onResume");
            }
        });
        XposedHelpers.findAndHookMethod(MainActivity, "onDestroy", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("MainActivity onDestroy");
                mainActivityObj = null;
            }
        });

        DYLoginActivityCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.account.white.login.DYLoginActivity", classLoader);
        XposedHelpers.findAndHookMethod(DYLoginActivityCls, "onCreate", Bundle.class, new XC_MethodHook() {

            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("DYLoginActivity onCreate");
                Bundle bundle = (Bundle) param.args[0];
                TraceUtil.e("DYLoginActivity onCreate bundle: " + bundle);
                dYLoginActivityObj = (Activity) param.thisObject;
                mainHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (mOperEnum == DyOperEnum.login || mOperEnum == DyOperEnum.message) {
                            loginOper(dYLoginActivityObj, mPhone, mPass);
                        } else if (mOperEnum == DyOperEnum.sendCode) {
                            sendCodeOper(dYLoginActivityObj, mPhone);
                        }
                    }
                }, 1000);
            }
        });
        XposedHelpers.findAndHookMethod(DYLoginActivityCls, "onResume", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("DYLoginActivity onResume");
            }
        });
        XposedHelpers.findAndHookMethod(DYLoginActivityCls, "onDestroy", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("DYLoginActivity onDestroy");
                dYLoginActivityObj = null;
            }
        });
        XposedHelpers.findAndHookMethod(DYLoginActivityCls, "a", Bundle.class, new XC_MethodHook() {

            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                Bundle bundle = (Bundle) param.args[0];
                TraceUtil.e("DYLoginActivity prev bundle: " + bundle.toString());
                if (dyLoginBundle != null) {
                    param.args[0] = dyLoginBundle;
                    TraceUtil.e("DYLoginActivity new  bundle: " + dyLoginBundle.toString());
                    dyLoginBundle = null;
                }
            }
        });

        UpdatePasswordActivityCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.account.white.updatepassword.DYUpdatePasswordActivity", classLoader);
        XposedHelpers.findAndHookMethod(UpdatePasswordActivityCls, "onCreate", Bundle.class, new XC_MethodHook() {

            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("DYUpdatePasswordActivity onCreate");
                updatePasswordActivityObj = (Activity) param.thisObject;
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mOperEnum == DyOperEnum.smsReg) {
                            updatePasswordOper(updatePasswordActivityObj, mPass);
                        }
                    }
                });
            }
        });
        XposedHelpers.findAndHookMethod(UpdatePasswordActivityCls, "onResume", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("DYUpdatePasswordActivity onResume");
            }
        });
        XposedHelpers.findAndHookMethod(UpdatePasswordActivityCls, "onDestroy", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("DYUpdatePasswordActivity onDestroy");
                updatePasswordActivityObj = null;
            }
        });


        Class RecommendContactActivityCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.friends.ui.RecommendContactActivity", classLoader);
        XposedHelpers.findAndHookMethod(RecommendContactActivityCls, "onCreate", Bundle.class, new XC_MethodHook() {

            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("RecommendContactActivityCls onCreate");
                final Activity activity = (Activity) param.thisObject;
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        final int skipId = activity.getResources().getIdentifier("fsd", "id", activity.getPackageName());
                        mainHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                (activity.findViewById(skipId)).performClick();
                            }
                        }, 500);
                    }
                });
            }
        });
    }

    private void hookIM(final ClassLoader classLoader, final Context context) {
        TraceUtil.e("hookIM");
        IntentFilter filter = new IntentFilter();
        filter.addAction(DyOperEnum.message.getBroadcast());

        context.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(final Context context, final Intent intent) {
                String action = intent.getAction();
                String conversationId = intent.getStringExtra("conversationId");
                String type = intent.getStringExtra("type");
                if ("msg".equals(type)) {
                    String msg = intent.getStringExtra("msg");
                    TraceUtil.e("receive im broadcast, conversationId = " + conversationId + ", send msg = " + msg);
                    sendMsg(classLoader, context, conversationId, msg);
                } else if ("url".equals(type)) {
                    String url = intent.getStringExtra("url");
                    String title = intent.getStringExtra("title");
                    String desc = intent.getStringExtra("desc");
                    String image = intent.getStringExtra("image");
                    TraceUtil.e("receive im broadcast, conversationId = " + conversationId + ", url = " + url + ", title = " + title + ", desc = " + desc + ", image = " + image);
                    sendUrl(classLoader, context, conversationId, url, title, desc, image);
                } else if ("userId".equals(type)) {
                    String userId = intent.getStringExtra("userId");
                    TraceUtil.e("receive im broadcast, userId = " + userId);
                    if (mainActivityObj != null) {
                        startChat(classLoader, mainActivityObj, userId, null);
                    }
                }
            }
        }, filter);

        // 抖音的首页Fragment
        Class MainPageFragment = XposedHelpers.findClass("com.ss.android.ugc.aweme.main.MainPageFragment", classLoader);
        XposedHelpers.findAndHookMethod(MainPageFragment, "onActivityCreated", Bundle.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("MainPageFragment onActivityCreated");
                mainPageFragmentObj = param.thisObject;
            }
        });
        XposedHelpers.findAndHookMethod(MainPageFragment, "onDestroyView", new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("MainPageFragment onDestroyView");
                mainPageFragmentObj = null;
            }
        });
        XposedHelpers.findAndHookMethod(MainPageFragment, "onResume", new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("MainPageFragment onResume");

                if (mOperEnum == DyOperEnum.message && !TextUtils.isEmpty(mUserId)) {
                    mainHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            // TraceUtil.e("MainPageFragment exitGuideView");
                            // XposedHelpers.callMethod(mainPageFragmentObj, "exitGuideView");
                            TraceUtil.e("MainPageFragment toNotifyPage");
                            if (mainPageFragmentObj != null) {
                                XposedHelpers.callMethod(mainPageFragmentObj, "toNotifyPage");
                            }
                        }
                    }, 3000);
                    mainHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                JSONArray arr = new JSONArray(mMessageList);
                                JSONObject jobj = arr.getJSONObject(0);
                                String targetUid = jobj.optString("userId");

                                startChat(classLoader, mainActivityObj, targetUid, new Callback() {
                                    @Override
                                    public void onSuccess(Object data) {
                                        TraceUtil.e("****** send msg ******");
                                        try {
                                            JSONArray arr = new JSONArray(mMessageList);
                                            for (int i = 0; i < arr.length(); i++) {
                                                JSONObject jobj = arr.getJSONObject(i);
                                                String targetUid = jobj.optString("userId");
                                                String conversationId = "";
                                                try {
                                                    if (Long.valueOf(mUserId) < Long.valueOf(targetUid)) {
                                                        conversationId = "0:1:" + mUserId + ":" + targetUid;
                                                    } else {
                                                        conversationId = "0:1:" + targetUid + ":" + mUserId;
                                                    }
                                                } catch (NumberFormatException e) {
                                                    e.printStackTrace();
                                                }
                                                if (TextUtils.isEmpty(conversationId)) {
                                                    TraceUtil.e("dy send msg error, conversationId is null");
                                                    return;
                                                }

                                                String finalConversationId = conversationId;
                                                if (jobj.has("text")) {
                                                    String msg = jobj.optString("text");
                                                    mainHandler.postDelayed(new Runnable() {
                                                        @Override
                                                        public void run() {
                                                            sendMsg(classLoader, context, finalConversationId, msg);
                                                        }
                                                    }, i * 500);

                                                } else if (jobj.has("url")) {
                                                    String url = jobj.optString("url");
                                                    String title = jobj.optString("title");
                                                    String desc = jobj.optString("desc");
                                                    String image = jobj.optString("image");
                                                    mainHandler.postDelayed(new Runnable() {
                                                        @Override
                                                        public void run() {
                                                            sendUrl(classLoader, context, finalConversationId, url, title, desc, image);
                                                        }
                                                    }, i * 500);
                                                }
                                            }

                                            mainHandler.postDelayed(new Runnable() {
                                                @Override
                                                public void run() {
                                                    TraceUtil.e("****** dy send msg end ******");
                                                    sendResult(mainActivityObj, DyOperEnum.message.getResult(), 0, null, "发送成功");
                                                    exitApp(context);
                                                }
                                            }, arr.length() * 500 + 3000);
                                            mUserId = null;
                                        } catch (JSONException e) {
                                            e.printStackTrace();
                                        }
                                    }

                                    @Override
                                    public void onFailure(String error) {

                                    }
                                });

                            } catch (JSONException e) {
                                e.printStackTrace();
                            }

                        }
                    }, 6000);
                }
            }
        });
        XposedHelpers.findAndHookMethod(MainPageFragment, "onTabChanged", String.class, String.class, boolean.class, boolean.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                super.afterHookedMethod(param);
                TraceUtil.e("MainPageFragment onTabChanged param0 = " + param.args[0] + ", param1 = " + param.args[1] + ", param2 = " + param.args[2] + ", param3 = " + param.args[3]);
            }
        });

        Class ChatRoomActivity = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.sdk.chat.ChatRoomActivity", classLoader);
        XposedHelpers.findAndHookMethod(ChatRoomActivity, "onCreate", Bundle.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("ChatRoomActivity onCreate bundle: " + ((param.args[0]) != null ? (param.args[0]).toString() : "null"));
            }
        });

        XposedHelpers.findAndHookMethod(ChatRoomActivity, "onDestroy", new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("ChatRoomActivity onDestroy");
            }
        });

        // 在主页发起私聊参数监听
        Class YCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.y", classLoader);
        XposedHelpers.findAndHookMethod(YCls, "a", String.class, String.class, String.class, String.class, String.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("im y: param1 = " + param.args[0] + ", param2 = " + param.args[1] + ", param3 = " + param.args[2] + ", param4 = " + param.args[3] + ", param5 = " + param.args[4]);
            }
        });

        Class IMServiceCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.sdk.providedservices.IMService", classLoader);
        Class IMUserCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.service.model.IMUser", classLoader);
        Class ModelFCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.service.model.f", classLoader);
        XposedHelpers.findAndHookMethod(IMServiceCls, "wrapperChatWithSyncXAlert", Activity.class, IMUserCls, int.class, ModelFCls, Serializable.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("im wrapperChatWithSyncXAlert: activity = " + ((Activity) param.args[0]).getComponentName());
                TraceUtil.e("im wrapperChatWithSyncXAlert: user = " + JSON.toJSONString(param.args[1]));
                TraceUtil.e("im wrapperChatWithSyncXAlert: int = " + JSON.toJSONString(param.args[2]));
                TraceUtil.e("im wrapperChatWithSyncXAlert: model = " + JSON.toJSONString(param.args[3]));
                TraceUtil.e("im wrapperChatWithSyncXAlert: serializable = " + JSON.toJSONString(param.args[4]));
            }
        });

        XposedHelpers.findAndHookMethod(IMServiceCls, "wrapperChatWithSyncXAlert", Activity.class, IMUserCls, int.class, Serializable.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("im wrapperChatWithSyncXAlert: activity = " + ((Activity) param.args[0]).getComponentName());
                TraceUtil.e("im wrapperChatWithSyncXAlert: user = " + JSON.toJSONString(param.args[1]));
                TraceUtil.e("im wrapperChatWithSyncXAlert: int = " + JSON.toJSONString(param.args[2]));
                TraceUtil.e("im wrapperChatWithSyncXAlert: serializable = " + JSON.toJSONString(param.args[3]));
            }
        });

        // 发送消息参数监听
        Class ImCoreApiBGCls = XposedHelpers.findClass("com.bytedance.ies.im.core.api.b.g", classLoader);
        Object imCoreApiBGBObj = XposedHelpers.callStaticMethod(ImCoreApiBGCls, "a");
        Class ImCoreApiBGBCls = imCoreApiBGBObj.getClass();
        XposedHelpers.findAndHookMethod(ImCoreApiBGBCls, "b", String.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("im core param: conversationId = " + param.args[0]);
            }
        });

        XposedHelpers.findAndHookMethod(ImCoreApiBGBCls, "a", XposedHelpers.findClass("com.bytedance.ies.im.core.api.f.c", classLoader), new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("im core param: content = " + JSON.toJSONString(param.args[0]));
            }
        });

        XposedHelpers.findAndHookMethod(ImCoreApiBGBCls, "a", XposedHelpers.findClass("com.bytedance.ies.im.core.api.f.b", classLoader), new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("im core param: model = " + JSON.toJSONString(param.args[0]));
            }
        });

        XposedHelpers.findAndHookMethod(ImCoreApiBGBCls, "a", Map.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("im core param: map = " + JSON.toJSONString(param.args[0]));
            }
        });

        XposedHelpers.findAndHookMethod(ImCoreApiBGBCls, "a", List.class, new XC_MethodHook() {
            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                super.beforeHookedMethod(param);
                TraceUtil.e("im core param: list content = " + JSON.toJSONString(param.args[0]));
            }
        });
    }

    // 文本消息的主要逻辑：com.ss.android.ugc.aweme.im.sdk.chat.input.InputViewAb -> a()
    private void sendMsg(final ClassLoader classLoader, final Context context, final String conversationId, final String msg) {
        TraceUtil.e("send msg: conversationId = " + conversationId + ", msg = " + msg);
        Class ImCoreApiBGCls = XposedHelpers.findClass("com.bytedance.ies.im.core.api.b.g", classLoader);
        Object imCoreApiBGBObj = XposedHelpers.callStaticMethod(ImCoreApiBGCls, "a");

        imCoreApiBGBObj = XposedHelpers.callMethod(imCoreApiBGBObj, "b", conversationId);

        Class TextContentCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.sdk.chat.model.TextContent", classLoader);
        Object textContentObj = XposedHelpers.callStaticMethod(TextContentCls, "obtain", msg);
        XposedHelpers.callMethod(textContentObj, "setSendStartTime", System.currentTimeMillis());
        imCoreApiBGBObj = XposedHelpers.callMethod(imCoreApiBGBObj, "a", textContentObj);

        Class ModelCCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.sdk.model.c", classLoader);
        Object modelCObj = XposedHelpers.newInstance(ModelCCls);
        imCoreApiBGBObj = XposedHelpers.callMethod(imCoreApiBGBObj, "a", modelCObj);

        XposedHelpers.callMethod(imCoreApiBGBObj, "a");
    }

    // 分享链接的主要逻辑：com.ss.android.ugc.aweme.im.sdk.share.a.c -> a(List<String> list, String str, BaseContent baseContent, com.ss.android.ugc.aweme.im.sdk.model.c cVar)
    private void sendUrl(final ClassLoader classLoader, final Context context, final String conversationId, final String url, String title, String desc, String image) {
        TraceUtil.e("send msg: conversationId = " + conversationId + ", url = " + url + ", title = " + title + ", desc = " + desc + ", image = " + image);
        Class ImCoreApiBGCls = XposedHelpers.findClass("com.bytedance.ies.im.core.api.b.g", classLoader);
        Object imCoreApiBGBObj = XposedHelpers.callStaticMethod(ImCoreApiBGCls, "a");

        // 设置conversationId
        imCoreApiBGBObj = XposedHelpers.callMethod(imCoreApiBGBObj, "b", conversationId);
        // 设置hashMap
        imCoreApiBGBObj = XposedHelpers.callMethod(imCoreApiBGBObj, "a", new HashMap<String, String>());
        // 设置model
        Class ModelCCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.sdk.model.c", classLoader);
        Object modelCObj = XposedHelpers.newInstance(ModelCCls);
        XposedHelpers.setObjectField(modelCObj, "a", "message_long_press");
        XposedHelpers.setObjectField(modelCObj, "b", "chat_forward");
        XposedHelpers.setObjectField(modelCObj, "g", UUID.randomUUID().toString());
        imCoreApiBGBObj = XposedHelpers.callMethod(imCoreApiBGBObj, "a", modelCObj);
        // 设置分享链接
        Class ShareWebContentCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.sdk.chat.model.ShareWebContent", classLoader);
        Object shareWebContentObj = XposedHelpers.newInstance(ShareWebContentCls);
        XposedHelpers.callMethod(shareWebContentObj, "setTitle", title);
        XposedHelpers.callMethod(shareWebContentObj, "setDesc", desc);
        XposedHelpers.callMethod(shareWebContentObj, "setImage", image);
        XposedHelpers.callMethod(shareWebContentObj, "setUrl", url);
        XposedHelpers.setIntField(shareWebContentObj, "aweType", 0);
        XposedHelpers.setIntField(shareWebContentObj, "type", 0);
        XposedHelpers.setObjectField(shareWebContentObj, "hint", "转发[链接]：" + title);
        XposedHelpers.callMethod(shareWebContentObj, "setPushDetail", title);

        imCoreApiBGBObj = XposedHelpers.callMethod(imCoreApiBGBObj, "a", shareWebContentObj);

        XposedHelpers.callMethod(imCoreApiBGBObj, "a");
    }

    // {before_jump_finish_current=false, next_page_need_to_jump=2, trigger=0, need_hide_login_way=, enter_from=homepage_hot, enter_method=click_message, last_page_jump_here=0, current_show_page=1, can_back_to_last_page=false, auth_app=, login_last_platform_trust=0, login_title=登录后即可查看消息}
    private void loginPage() {
        if (mainActivityObj != null) {
            TraceUtil.e("****** dy passport login start ******");
            Bundle bundle = new Bundle();
            bundle.putBoolean("before_jump_finish_current", false);
            bundle.putInt("next_page_need_to_jump", 2);
            bundle.putInt("trigger", 0);
            bundle.putString("need_hide_login_way", "");
            bundle.putString("enter_from", "homepage_hot");
            bundle.putString("enter_method", "click_message");
            bundle.putInt("last_page_jump_here", 0);
            bundle.putInt("current_show_page", 1);
            bundle.putBoolean("can_back_to_last_page", false);
            bundle.putString("auth_app", "");
            bundle.putInt("login_last_platform_trust", 0);
            bundle.putString("login_title", "登录后即可查看消息");
            dyLoginBundle = bundle;
            Intent intent = new Intent();
            intent.setClass(mainActivityObj, DYLoginActivityCls);
            mainActivityObj.startActivity(intent);
        }
    }

    private void loginOper(final Activity activity, String phone, final String pass) {
        final Object phoneObj = XposedHelpers.newInstance(PhoneBeanCls);
        XposedHelpers.callMethod(phoneObj, "setNationalNumber", Long.valueOf(phone));

        final int phoneLayoutId = activity.getResources().getIdentifier("eeo", "id", activity.getPackageName());
        final int passId = activity.getResources().getIdentifier("ecy", "id", activity.getPackageName());
        final int checkId = activity.getResources().getIdentifier("eso", "id", activity.getPackageName());
        final int buttonId = activity.getResources().getIdentifier("c0l", "id", activity.getPackageName());

        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                Object phoneLayout = activity.findViewById(phoneLayoutId);
                XposedHelpers.callMethod(phoneLayout, "setPhoneNumber", phoneObj);
                ((EditText) activity.findViewById(passId)).setText(pass);
                ((Checkable) activity.findViewById(checkId)).setChecked(true);
            }
        });
        mainHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                (activity.findViewById(buttonId)).performClick();
            }
        }, 500);
        if (mOperEnum == DyOperEnum.login) {
            mainHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (isPassLoginSuccess) {
                        TraceUtil.e("****** dy passport login end ******");
                        sendResult(mainActivityObj, DyOperEnum.login.getResult(), 1, null, "登录超时");
                        clearExitApp(activity);
                    }
                }
            }, 10500);
        } else if (mOperEnum == DyOperEnum.message) {
            mainHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (isPassLoginSuccess) {
                        TraceUtil.e("dy send msg 超时");
                        sendResult(mainActivityObj, DyOperEnum.message.getResult(), 1, null, "发送超时");
                        clearExitApp(mainActivityObj);
                    }
                }
            }, 40000);
        }
    }

    // {before_jump_finish_current=true, next_page_need_to_jump=1, trigger=0, need_hide_login_way=, enter_from=homepage_hot, enter_method=click_message, current_show_page=0, can_back_to_last_page=false, auth_app=, login_last_platform_trust=0, login_title=登录后即可查看消息}
    private void sendCodePage() {
        if (mainActivityObj != null) {
            TraceUtil.e("****** dy passport send code start ******");
            Bundle bundle = new Bundle();
            bundle.putBoolean("before_jump_finish_current", true);
            bundle.putInt("next_page_need_to_jump", 1);
            bundle.putInt("trigger", 0);
            bundle.putString("need_hide_login_way", "");
            bundle.putString("enter_from", "homepage_hot");
            bundle.putString("enter_method", "click_message");
            bundle.putInt("current_show_page", 0);
            bundle.putBoolean("can_back_to_last_page", false);
            bundle.putString("auth_app", "");
            bundle.putInt("login_last_platform_trust", 0);
            bundle.putString("login_title", "登录后即可查看消息");
            dyLoginBundle = bundle;
            Intent intent = new Intent();
            intent.setClass(mainActivityObj, DYLoginActivityCls);
            mainActivityObj.startActivity(intent);
        }
    }

    private void sendCodeOper(final Activity activity, String phone) {
        final Object phoneObj = XposedHelpers.newInstance(PhoneBeanCls);
        XposedHelpers.callMethod(phoneObj, "setNationalNumber", Long.valueOf(phone));

        final int phoneLayoutId = activity.getResources().getIdentifier("eeo", "id", activity.getPackageName());
        final int buttonId = activity.getResources().getIdentifier("bps", "id", activity.getPackageName());

        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                Object phoneLayout = activity.findViewById(phoneLayoutId);
                XposedHelpers.callMethod(phoneLayout, "setPhoneNumber", phoneObj);
            }
        });

        mainHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                (activity.findViewById(buttonId)).performClick();
            }
        }, 500);
    }

    /**
     * 如果password为空，进行简单的验证码登录
     * 如果password不为空，跳转到修改密码界面，修改密码
     *
     * @param activity
     * @param code
     * @param password
     */
    private void smsLoginOper(final Activity activity, final String code, final String password) {
        if (activity == null) {
            return;
        }

        TraceUtil.e("****** dy passport sms login start ******");
        final int codeId = activity.getResources().getIdentifier("ftn", "id", activity.getPackageName());
        final int checkId = activity.getResources().getIdentifier("eso", "id", activity.getPackageName());
        final int buttonId = activity.getResources().getIdentifier("c0l", "id", activity.getPackageName());

        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                EditText ed = (EditText) activity.findViewById(codeId);
                if (ed != null) {
                    ed.setText(code);
                    ((Checkable) activity.findViewById(checkId)).setChecked(true);
                }
            }
        });

        mainHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                (activity.findViewById(buttonId)).performClick();
            }
        }, 500);

        mainHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (TextUtils.isEmpty(password)) {
                    TraceUtil.e("****** dy passport sms login end ******");
                    sendResult(mainActivityObj, DyOperEnum.smsLogin.getResult(), 1, null, "登录超时");
                    clearExitApp(activity);
                } else {
                    updatePasswordPage();
                }
            }
        }, 10500);
    }

    private void updatePasswordPage() {
        if (mainActivityObj != null) {
            TraceUtil.e("****** dy update passport start ******");
            Activity act = mainActivityObj;
            Intent intent = new Intent();
            intent.setClass(act, UpdatePasswordActivityCls);
            act.startActivity(intent);
        }
    }

    private void updatePasswordOper(final Activity activity, final String pass) {
        if (activity == null) {
            return;
        }

        final int passId = activity.getResources().getIdentifier("ecy", "id", activity.getPackageName());
        final int buttonId = activity.getResources().getIdentifier("e4g", "id", activity.getPackageName());

        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                EditText ed = (EditText) activity.findViewById(passId);
                if (ed != null) {
                    ed.setText(pass);
                }
            }
        });

        mainHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                (activity.findViewById(buttonId)).performClick();
                sendResult(mainActivityObj, DyOperEnum.smsReg.getResult(), 0, null, "");
                TraceUtil.e("****** dy update passport end ******");
            }
        }, 500);
    }

    private void smsConfirmUpdatePasswordOper(final Activity activity, final String code) {
        if (activity == null) {
            return;
        }

        TraceUtil.e("****** dy sms confirm update passport start ******");
        final int codeId = activity.getResources().getIdentifier("ftn", "id", activity.getPackageName());
        final int buttonId = activity.getResources().getIdentifier("e4g", "id", activity.getPackageName());

        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                EditText ed = (EditText) activity.findViewById(codeId);
                if (ed != null) {
                    ed.setText(code);
                }
            }
        });

        mainHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                (activity.findViewById(buttonId)).performClick();
            }
        }, 500);

        mainHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                TraceUtil.e("****** dy sms confirm update passport end ******");
                sendResult(mainActivityObj, DyOperEnum.smsUpdatePassword.getResult(), 0, mLoginInfo, "");
                clearExitApp(activity);
            }
        }, 3500);
    }

    private void clearApp() {
        TraceUtil.e("****** dy clear app start ******");

        String baseInner = "/data/user/0/" + HookMain.PACKAGE_ID_NORM + "/";
        String baseExternal = "/storage/emulated/0/Android/data/" + HookMain.PACKAGE_ID_NORM + "/";

        // 删除SharedPreferences 账户信息
        File file = new File(baseInner + "shared_prefs/aweme_user.xml");
        FileUtil.deleteFile(file);
        // 删除SharedPreferences cdid信息
        file = new File(baseInner + "shared_prefs/com.ss.android.deviceregister.utils.Cdid.xml");
        FileUtil.deleteFile(file);
        // 删除SharedPreferences udid、udid_list、openudid、clientudid、serial_number信息
        file = new File(baseInner + "shared_prefs/snssdk_openudid.xml");
        FileUtil.deleteFile(file);
        // 删除SharedPreferences device_id信息
        file = new File(baseInner + "shared_prefs/applog_stats.xml");
        FileUtil.deleteFile(file);
        // 删除SharedPreferences cookies缓存
        file = new File(baseInner + "shared_prefs/ttnetCookieStore.xml");
        FileUtil.deleteFile(file);

        // 删除Files 下的device信息
        file = new File(baseInner + "files/keva/repo/");
        FileUtil.deleteDirWithFile(file);
        TraceUtil.e("keva/repo 文件夹已清空！");
        // 删除APP_WEBVIEW下cookies缓存
        file = new File(baseInner + "app_webview/Cookies");
        FileUtil.deleteFile(file);

        // 删除contentProvider device_id信息
        file = new File(baseExternal + "bytedance/device_parameters.dat");
        FileUtil.deleteFile(file);

        // 删除com.snssdk.api device_id信息
        file = new File(baseExternal + "bytedance/device_parameters.dat");
        String snssdkPath = file.getAbsolutePath().replace(HookMain.PACKAGE_ID_LITE, "com.snssdk.api");
        file = new File(snssdkPath);
        FileUtil.deleteFile(file);

        // 删除sdcard device_id信息
        file = new File("/storage/emulated/0/bytedance/device_parameters.dat");
        FileUtil.deleteFile(file);

        TraceUtil.e("****** dy clear app end ******");
    }

    private void exitApp(Context context) {
        TraceUtil.e("****** dy exit app start ******");

        // 退出app
        // 需要禁止app后台运行，否则退出app后会自动重启
        ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.AppTask> appTaskList = activityManager.getAppTasks();
        for (ActivityManager.AppTask appTask : appTaskList) {
            appTask.finishAndRemoveTask();
        }
        TraceUtil.e("****** dy exit app end ******");
        System.exit(0);
    }

    private void clearExitApp(Context context) {
        if (context == null) {
            return;
        }

        clearApp();
        // 发送关闭app结果
        mOperEnum = DyOperEnum.exit;
        sendResult(context, DyOperEnum.exit.getResult(), 0, null, "");
        exitApp(context);
    }

    private void clearExitAppNoRes(Context context) {
        if (context == null) {
            return;
        }

        clearApp();
        exitApp(context);
    }


    private void sendResult(Context context, String action, int code, JSONObject data, String msg) {
        if (context != null && mOperEnum != DyOperEnum.unknown) {
            JSONObject obj = new JSONObjectPack()
                    .putValue("code", code)
                    .putValue("data", (data == null ? new JSONObject() : data))
                    .putValue("msg", msg)
                    .getJSONObject();
            Intent intent = new Intent(action);
            intent.putExtra("data", obj.toString());
            context.sendBroadcast(intent);
        }
        mOperEnum = DyOperEnum.unknown;
    }

    private void startChat(ClassLoader classLoader, Activity act, String uid, Callback call) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                Object iMUser = null;
                for (int cnt = 0; cnt < 3; cnt++) {
                    Class ImSdkBHCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.sdk.b.h", classLoader);
                    iMUser = XposedHelpers.callStaticMethod(ImSdkBHCls, "a", uid, "null");
                    TraceUtil.e("getIMUser " + cnt + ": uid = " + uid + ", iMUser = " + JSON.toJSONString(iMUser));
                    if (iMUser == null) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        cnt = 3;
                    }
                }

                if (iMUser == null) {
                    TraceUtil.e("startChat失败，获取iMUser超时");
                    if (call != null) {
                        call.onFailure("startChat失败，获取iMUser超时");
                    }
                } else {
                    final Object fIMUser = iMUser;
                    mainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            Class IMUserCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.service.model.IMUser", classLoader);
                            Class ModelFCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.service.model.f", classLoader);
                            Class ImQCls = XposedHelpers.findClass("com.ss.android.ugc.aweme.im.q", classLoader);
                            Object IMServiceObj = XposedHelpers.callStaticMethod(ImQCls, "e");
                            XposedHelpers.callMethod(IMServiceObj, "wrapperChatWithSyncXAlert", new Class[]{Activity.class, IMUserCls, int.class, ModelFCls, Serializable.class}, act, fIMUser, 3, null, null);
                        }
                    });

                    if (call != null) {
                        mainHandler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                TraceUtil.e("startChat成功");
                                call.onSuccess("startChat成功");
                            }
                        }, 4000);
                    }
                }
            }
        });
    }
}


